#include "CubicSpline.hpp"
#include "matplotlibcpp.h"
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <vector>
#include <algorithm>

using namespace std;

double f(double x){
    return 1/(1+25*x*x);
}

void draw(vector<double> xData, vector<vector<double> > yData, string file_name){
    int n = yData.size();
    plt::figure_size(1200, 780); 
    vector<string> num_of_p = {"6", "11", "21", "41", "81"};
    for (int i = 0; i < n; ++i) {
        plt::plot(xData, yData[i],{{"label", num_of_p[i]}});
    }
    plt::title("plot of A");
    plt::save(file_name,300);
    plt::legend();
}

int main() {
    std::cout << "----- running A -----" << std::endl;

    vector<int> N = {6, 11, 21, 41, 81};
    int n = N.size();
    vector<CubicSpline> spline(n);
    vector<double> max_error(n);
    // 定义变量储存差值曲线
    vector<vector<double> > yValue;
    vector<double> xValue;
    double stepsize = 0.01;
    double current = -1;
    while(current <= 1){
        xValue.push_back(current);
        current += stepsize;
    }
    
    for(int i=0; i<n; i++){
        // 定义数据点和误差
        vector<double> xData(N[i]);
        vector<double> yData(N[i]);
        vector<double> error(N[i]-1);
        // 搭建插值样条
        for (int j = 0; j < N[i]; j++) {
            xData[j] = -1.0 + 2.0*j/(N[i]-1);
            yData[j] = f(xData[j]);
        }
        spline[i].setData(xData, yData);
        spline[i].setBoundary(CubicSpline::natural);
        spline[i].setupSplines();
        // 计算误差
        for (int j=0; j<N[i]-1; j++) {
            double x = (xData[j] + xData[j+1])/2;
            error[j] = abs(f(x) - spline[i].interpolate(x));
        }
        max_error[i] = *max_element(error.begin(), error.end());
        // 计算差值曲线
        vector<double> y;
        for (double x : xValue) {
            y.push_back(spline[i].interpolate(x));
        }
        yValue.push_back(y);
    }
    draw(xValue, yValue, "../figure/A_plot.png");

    // 输出结果
    cout << "max error change as below:" << endl;
    cout << "N:  " << " |--"<<N[0]<<"--|"  <<  "    |--"<<N[1]<<"--|"  <<  "    |--"<<N[2]<<"--|"  <<  "    |--"<<N[3]<<"--|"  <<  "    |--"<<N[4]<<"--|"  << endl;  
    cout << "error:" << max_error[0] << setw(12) << max_error[1] << setw(12) << max_error[2] << setw(12) << max_error[3] << setw(12) << max_error[4] <<endl;

    std::cout << "----- complete A -----" << std::endl;
}


